#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <unistd.h>
#include "task.hpp"
#include "blockQueue.hpp"

using std:: cout;
using std:: endl;

//-------------------------------------------------------------------------------------------------
//简单的示例：缓冲区的数据为整数 

// void* concumer(void* args)
// {
//     blockQueue<int>* bq = static_cast<blockQueue<int>*>(args);
//     while(true)
//     {
//         sleep(1);
//         int data = 0;
//         //1.从缓冲区中获取数据
//         bq->pop(&data);
//         //2.将数据进行处理   -- TODO 后面做
//         //这里简单的打印一下
//         cout << "consumer get data: " << data << endl;
//     }
//     return nullptr;
// }
// void* producer(void* args)
// {
//     blockQueue<int>* bq = static_cast<blockQueue<int>*>(args);
//     while(true)
//     {
//         //1.通过某种渠道获取数据
//         int data = rand() % 10 + 1;
//         //2.将数据放到缓冲区
//         cout << "producer push data: " << data << endl;
//         bq->push(data);    
//     }
//     return nullptr;
// }


//-------------------------------------------------------------------------------------------------
//缓冲区的数据是可以是类，可以是一个一个的任务
//这还只是一个简单任务，未来呢是不是可以从网络中获取一个一个的任务，再将它放到阻塞队列中，让生产者来消费呢
//是可以的，这才是它的真正用途

void* concumer(void* args)
{
    blockQueue<Task>* bq = static_cast<blockQueue<Task>*>(args);
    while(true)
    {
        Task t;
        //1.从缓冲区中获取数据
        bq->pop(&t);
        //2.将数据进行处理   -- TODO 后面做
        t(); //对任务进行处理
        cout << pthread_self() << "consumer get data: " << t.formatExpression() << t.formatResult() << endl;
    }
    return nullptr;
}

void* producer(void* args)
{
    blockQueue<Task>* bq = static_cast<blockQueue<Task>*>(args);
    std:: string ops = "+-*/%";
    while(true)
    {
        sleep(1);
        //1.通过某种渠道获取数据
        int x = rand() % 10;
        int y = rand() % 20;
        char op = ops[ rand() % ops.size() ];
        Task t(x,y,op);

        //2.将数据放到缓冲区
        bq->push(t);    
        cout << pthread_self() << "producer push task: " << t.formatExpression() << " ?" << endl;
    }
    return nullptr;
}

//单生产单消费 --> 只要维护生产者和消费者之间的关系
int main()
{
    // blockQueue<int>* bq = new blockQueue<int>(); //缓冲区
    blockQueue<Task>* bq = new blockQueue<Task>(); //缓冲区
    //两个线程要看到同一个交易场所，因此得将这个交易场所作为参数传递给两个线程  or  将缓冲区作为全局变量
    
    // 单生产单消费
    // pthread_t c,p;
    // pthread_create(&c,nullptr,concumer,bq);
    // pthread_create(&p,nullptr,producer,bq);
    // pthread_join(c,nullptr);
    // pthread_join(p,nullptr);

    // blockQueue的代码是可以hold的住多生产多消费，因为只使用了一把锁，该锁不仅维护了生产者与生产者之间的互斥，
    // 维护了生产者与消费者之间的互斥，还维护了消费者与消费者之间的互斥
    pthread_t c[3], p[2];
    pthread_create(c+0, nullptr, concumer, bq);
    pthread_create(c+1, nullptr, concumer, bq);
    pthread_create(c+2, nullptr, concumer, bq);
    pthread_create(p+0, nullptr, producer, bq);
    pthread_create(p+1, nullptr, producer, bq);

    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(c[2], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);

    return 0;
}


